home *** CD-ROM | disk | FTP | other *** search
/ Software Vault: The Gold Collection / Software Vault - The Gold Collection (American Databankers) (1993).ISO / cdr46 / vfwdk.zip / VFWSDK.ZIP / SAMPLES / WRITEAVI / WRITEAVI.C < prev    next >
C/C++ Source or Header  |  1993-02-04  |  11KB  |  389 lines

  1.  
  2. /****************************************************************************
  3.  *
  4.  *  WRITEAVI.C
  5.  *
  6.  *  Creates the file OUTPUT.AVI, an AVI file consisting of a rotating clock
  7.  *  face.  This program demonstrates using the functions in AVIEASY.C to make
  8.  *  writing AVI files simple.
  9.  *
  10.  *  Copyright (c) 1992-1993 Microsoft Corporation.  All Rights Reserved.
  11.  *
  12.  *  You have a royalty-free right to use, modify, reproduce and
  13.  *  distribute the Sample Files (and/or any modified version) in
  14.  *  any way you find useful, provided that you agree that
  15.  *  Microsoft has no warranty obligations or liability for any
  16.  *  Sample Application Files which are modified.
  17.  *
  18.  ***************************************************************************/
  19.  
  20. #include <windows.h>
  21. #include <mmsystem.h>
  22. #include "avieasy.h"
  23.  
  24. //
  25. // Our movie is 160x120 and 15 frames long
  26. //
  27. #define BITMAP_X    160
  28. #define BITMAP_Y    120
  29. #define N_FRAMES    15
  30.  
  31. #ifndef WIN32
  32. #define CODE  _based(_segname("_CODE"))
  33. #define STACK _based(_segname("_STACK"))
  34. #else
  35. #define CODE
  36. #define STACK
  37. #endif
  38.  
  39. //
  40. // A quick lookup table for Sin and Cos values
  41. //
  42. static int CODE aSin[N_FRAMES] = {
  43.     0,    40,    74,    95,    99,
  44.     86,    58,    20,    -20,    -58,
  45.     -86,    -99,    -95,    -74,    -40,
  46. } ;
  47.  
  48. static int CODE aCos[N_FRAMES] = {
  49.     100,    91,    66,    30,    -10,
  50.     -49,    -80,    -97,    -97,    -80,
  51.     -50,    -10,    30,    66,    91,
  52. } ;
  53.  
  54. static char CODE sz02U[]         = "%02u";
  55.  
  56. static void FreeFrames( LPBITMAPINFOHEADER FAR *alpbi) ;
  57. static void MakeFrames(LPBITMAPINFOHEADER FAR *alpbi, UINT bits, UINT wXSize,UINT wYSize ) ;
  58. static HANDLE MakeDib( HBITMAP hbitmap, UINT bits ) ;
  59.  
  60.  
  61. // 
  62. // Our main message loop... we don't have a window, we just pop up a dialog
  63. // box, write the file, and quit
  64. //
  65. int PASCAL WinMain(HANDLE hInstance, HANDLE hPrevInstance, LPSTR szCmdLine, int sw)
  66. {
  67.     LPBITMAPINFOHEADER alpbi[N_FRAMES];
  68.     HAVI        havi;
  69.     int            i;
  70.     
  71.     alpbi[0] = NULL;
  72.  
  73.     if (MessageBox(NULL, "This program writes some DIBs into a file called OUTPUT.AVI.  "
  74.            "We apologize for the lack of a user interface.",
  75.            "WriteAVI Sample",
  76.            MB_OKCANCEL) == IDCANCEL)
  77.     return 0;
  78.      
  79.     //
  80.     // Set up the bitmaps for the file in an array
  81.     //
  82.     MakeFrames(alpbi, 8, BITMAP_X, BITMAP_Y);
  83.  
  84.     //
  85.     // Since we are writing an AVI file with a single video stream, we have
  86.     // a helper function that will do both the avifileOpen and avifileAddStream
  87.     // for us
  88.     //
  89.     aviVideoOpen(&havi, "output.avi", alpbi[0], 0);
  90.  
  91.     //
  92.     // Now write out each video frame.  Again, since this is a file with only
  93.     // 1 stream (a video stream) we can use this function instead of
  94.     // avifileWrite to save a little work
  95.     //
  96.     for (i = 0; i < N_FRAMES; i++)
  97.     aviVideoWriteFrame(havi, alpbi[i], NULL, AVIIF_KEYFRAME);
  98.  
  99.     //
  100.     // Now close the file
  101.     //
  102.     avifileClose(havi);
  103.  
  104.     //
  105.     // Free the resources used to store the frames
  106.     //
  107.     FreeFrames(alpbi);
  108.     
  109.     return 0;
  110. }
  111.  
  112. //
  113. // Fill an array of LPBI's with the frames for this movie
  114. //
  115. static void MakeFrames(LPBITMAPINFOHEADER FAR *alpbi, UINT bits, UINT wXSize,UINT wYSize )
  116. {
  117.     HDC         hdc ;
  118.     HDC         hdcMem ;
  119.     HBITMAP     hbitmap,hbitmapOld ;
  120.     HPEN        hpen3,hpen1,hpenwhite,hpenOld ;
  121.     HFONT       hfont,hfontOld ;
  122.     HBRUSH      hbrush,hbrushOld ;
  123.     RECT        rc ;
  124.     RECT        rcFrameNo ;
  125.     int         wXCent,wYCent ;
  126.     int         cxPixInch ;
  127.     int         cyPixInch ;
  128.     int         cxPixels ;
  129.     int         cyPixels ;
  130.     int         radius ;
  131.     int         x0,y0,x1,y1 ;
  132.     int         i,j ;
  133.     char        ach[3] ;
  134.  
  135.     //
  136.     // Make sure our resources are freed
  137.     //
  138.     FreeFrames(alpbi);
  139.  
  140.     //
  141.     // Find the centre of the movie
  142.     //
  143.     wXCent = wXSize/2 ;
  144.     wYCent = wYSize/2 ;
  145.  
  146.     hdc = GetDC(NULL) ;
  147.     hdcMem = CreateCompatibleDC(NULL) ;
  148.  
  149.     //
  150.     // We need some gray and white brushes and pens, and a bitmap
  151.     //
  152.     hpen3 = CreatePen(PS_SOLID,3,RGB(128,128,128)) ;
  153.     hpen1 = CreatePen(PS_SOLID,1,RGB(64,64,64));
  154.     hpenwhite = CreatePen(PS_SOLID,1,RGB(255,255,255)) ;
  155.     hpenOld = SelectObject(hdcMem,hpen3) ;
  156.     hbrush = CreateSolidBrush(RGB(192,192,192)) ;
  157.     hbrushOld = SelectObject(hdcMem,hbrush) ;
  158.     hbitmap = CreateCompatibleBitmap(hdc,wXSize,wYSize) ;
  159.     hbitmapOld = SelectObject(hdcMem,hbitmap) ;
  160.  
  161.     cxPixInch = GetDeviceCaps(hdc,LOGPIXELSX) ;
  162.     cyPixInch = GetDeviceCaps(hdc,LOGPIXELSY) ;
  163.  
  164.     //
  165.     // What radius of circle can we fit in this frame?  Make sure it's round
  166.     // regardless of the aspect ratio
  167.     //
  168.     radius = ( wXSize < wYSize ) ? wXSize : (wYSize*cxPixInch)/cyPixInch ;
  169.     radius = ( radius * 95 ) / 200 ;
  170.  
  171.     //
  172.     // Make a Rectangle in the centre where the number will go
  173.     //
  174.     /* x0 = radius / sqrt(2) */
  175.     x0 = (radius*100)/141 ;
  176.     y0 = (x0*cyPixInch)/cxPixInch ;
  177.     x0 = (x0*9)/10 ;
  178.     y0 = (y0*9)/10 ;
  179.     SetRect( &rcFrameNo,wXCent-x0,wYCent-y0,wXCent+x0,wYCent+y0 ) ;
  180.  
  181.     //
  182.     // Move the rectangle in a little and make a font big enough for it
  183.     //
  184.     x0 = (x0*9)/10 ;
  185.     y0 = (y0*9)/10 ;
  186.  
  187.     hfont = CreateFont(
  188.         y0*2,
  189.         x0,
  190.         0,
  191.         0,
  192.         FW_BOLD,
  193.         0,
  194.         0,
  195.         0,
  196.         ANSI_CHARSET,
  197.         OUT_DEVICE_PRECIS,
  198.         CLIP_DEFAULT_PRECIS,
  199.         DEFAULT_QUALITY,
  200.         DEFAULT_PITCH|FF_SWISS,
  201.         NULL
  202.     ) ;
  203.  
  204.     hfontOld = SelectObject(hdcMem,hfont) ;
  205.  
  206.     //
  207.     // Now walk through and make all the frames
  208.     //
  209.     for ( i=0; i<N_FRAMES; i++ )
  210.     {
  211.     //
  212.     // Fill the whole frame with white
  213.     //
  214.         SetRect(&rc,0,0,wXSize,wYSize) ;
  215.         FillRect(hdcMem,&rc,(HBRUSH)GetStockObject(WHITE_BRUSH)) ;
  216.  
  217.     //
  218.     // Draw the circle inside the previously calculated radius
  219.     //
  220.         cxPixels = radius ;
  221.         cyPixels = (cxPixels*cyPixInch)/cxPixInch ;
  222.  
  223.         SelectObject(hdcMem,hpen3) ;
  224.         Ellipse(hdcMem,wXCent-cxPixels,wYCent-cyPixels,wXCent+cxPixels,
  225.         wYCent+cyPixels) ;
  226.  
  227.         SelectObject(hdcMem,hpen1) ;
  228.  
  229.     //
  230.     // Draw the number in the previously calculated area
  231.     //
  232.         wsprintf(ach,sz02U,i+1) ;
  233.  
  234.         SetBkColor(hdcMem,RGB(192,192,192)) ;
  235.         SetTextColor(hdcMem,RGB(255,255,255)) ;
  236.         ExtTextOut(
  237.             hdcMem,
  238.             rcFrameNo.left,rcFrameNo.top+(rcFrameNo.bottom-rcFrameNo.top)/20,
  239.             ETO_CLIPPED,
  240.             &rcFrameNo,
  241.             ach,
  242.             2,
  243.             NULL);
  244.  
  245.     //
  246.     // Draw tic marks around the inside of the circle in equal divisions
  247.     //
  248.         for ( j=0; j<N_FRAMES; j++ )
  249.         {
  250.             x0 = (radius*aSin[j])/100 ;
  251.             y0 = (radius*aCos[j])/100 ;
  252.             x1 = (((radius*aSin[j])/100)*11)/12 ;
  253.             y1 = (((radius*aCos[j])/100)*11)/12 ;
  254.  
  255.             y0 = -(y0*cyPixInch)/cxPixInch ;
  256.             y1 = -(y1*cyPixInch)/cxPixInch ;
  257.  
  258.             MoveTo(hdcMem,wXCent+x0,wYCent+y0) ;
  259.             LineTo(hdcMem,wXCent+x1,wYCent+y1) ;
  260.         }
  261.  
  262.     //
  263.     // Now draw the hand of the clock in the appropriate position
  264.     //
  265.         x1 = (((radius*aSin[i])/100)*5)/8 ;
  266.         y1 = (((radius*aCos[i])/100)*5)/8 ;
  267.         y1 = -(y1*cyPixInch)/cxPixInch ;
  268.  
  269.         MoveTo(hdcMem,wXCent,wYCent) ;
  270.         LineTo(hdcMem,wXCent+x1,wYCent+y1) ;
  271.  
  272.     //
  273.     // Make this into a DIB and stuff it into the array
  274.     //
  275.         alpbi[i] = (LPBITMAPINFOHEADER)GlobalLock(MakeDib(hbitmap, bits));
  276.  
  277.     //
  278.     // For an error, just duplicate the last frame if we can
  279.     //
  280.         if (alpbi[i] == NULL && i )
  281.             alpbi[i] = alpbi[i-1] ;
  282.     }
  283.  
  284.     //
  285.     // Select all the old objects back and delete resources
  286.     //
  287.     SelectObject(hdcMem,hpenOld) ;
  288.     SelectObject(hdcMem,hbrushOld) ;
  289.     SelectObject(hdcMem,hbitmapOld) ;
  290.     SelectObject(hdcMem,hfontOld) ;
  291.     DeleteObject(hpen1) ;
  292.     DeleteObject(hpen3) ;
  293.     DeleteObject(hpenwhite) ;
  294.     DeleteObject(hbrush) ;
  295.     DeleteObject(hbitmap) ;
  296.     DeleteObject(hfont) ;
  297.     DeleteObject(hdcMem) ;
  298.     ReleaseDC(NULL,hdc) ;
  299. }
  300.  
  301. //
  302. // Walk through our array of LPBI's and free them
  303. //
  304. static void FreeFrames(LPBITMAPINFOHEADER FAR *alpbi)
  305. {
  306.     UINT        w ;
  307.  
  308.     if (!alpbi[0])
  309.         return ;
  310.  
  311.     //
  312.     // Don't free a frame if it's a duplicate of the previous one
  313.     //
  314.     for (w=0; w<N_FRAMES; w++)
  315.         if (alpbi[w] && alpbi[w] != alpbi[w-1])
  316.             GlobalFree(SELECTOROF(alpbi[w]));
  317.  
  318.     for (w=0; w<N_FRAMES; w++)
  319.         alpbi[w] = NULL;
  320. }
  321.  
  322. /*
  323. ** MakeDib(hbitmap)
  324. **
  325. ** Take the given bitmap and transform it into a DIB with parameters:
  326. **
  327. ** BitsPerPixel:    8
  328. ** Colors:          palette
  329. **
  330. */
  331. static HANDLE  MakeDib( HBITMAP hbitmap, UINT bits )
  332. {
  333.     HANDLE              hdib ;
  334.     HDC                 hdc ;
  335.  
  336.     BITMAP              bitmap ;
  337.     UINT                wLineLen ;
  338.     DWORD               dwSize ;
  339.     DWORD               wColSize ;
  340.     LPBITMAPINFOHEADER  lpbi ;
  341.     LPBYTE              lpBits ;
  342.  
  343.     GetObject(hbitmap,sizeof(BITMAP),&bitmap) ;
  344.  
  345.     //
  346.     // DWORD align the width of the DIB
  347.     // Figure out the size of the colour table
  348.     // Calculate the size of the DIB
  349.     //
  350.     wLineLen = (bitmap.bmWidth*bits+31)/32 * 4;
  351.     wColSize = sizeof(RGBQUAD)*((bits <= 8) ? 1<<bits : 0);
  352.     dwSize = sizeof(BITMAPINFOHEADER) + wColSize +
  353.     (DWORD)(UINT)wLineLen*(DWORD)(UINT)bitmap.bmHeight;
  354.  
  355.     //
  356.     // Allocate room for a DIB and set the LPBI fields
  357.     //
  358.     if ((hdib = GlobalAlloc(GHND,dwSize)) == (HANDLE)NULL)
  359.         return hdib ;
  360.  
  361.     lpbi = (LPBITMAPINFOHEADER)GlobalLock(hdib) ;
  362.  
  363.     lpbi->biSize = sizeof(BITMAPINFOHEADER) ;
  364.     lpbi->biWidth = bitmap.bmWidth ;
  365.     lpbi->biHeight = bitmap.bmHeight ;
  366.     lpbi->biPlanes = 1 ;
  367.     lpbi->biBitCount = bits ;
  368.     lpbi->biCompression = BI_RGB ;
  369.     lpbi->biSizeImage = dwSize - sizeof(BITMAPINFOHEADER) - wColSize ;
  370.     lpbi->biXPelsPerMeter = 0 ;
  371.     lpbi->biYPelsPerMeter = 0 ;
  372.     lpbi->biClrUsed = (bits <= 8) ? 1<<bits : 0;
  373.     lpbi->biClrImportant = 0 ;
  374.  
  375.     //
  376.     // Get the bits from the bitmap and stuff them after the LPBI
  377.     //
  378.     lpBits = (LPBYTE)(lpbi+1)+wColSize ;
  379.  
  380.     hdc = CreateCompatibleDC(NULL) ;
  381.  
  382.     GetDIBits(hdc,hbitmap,0,bitmap.bmHeight,lpBits,(LPBITMAPINFO)lpbi,
  383.     DIB_RGB_COLORS);
  384.  
  385.     DeleteDC(hdc) ;
  386.  
  387.     return hdib ;
  388. }
  389.